package com.itheima.reggie.service.impl;

import com.fasterxml.jackson.databind.util.BeanUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.entity.dto.DishDto;
import com.itheima.reggie.entity.dto.SetmealDishDto;
import com.itheima.reggie.entity.dto.SetmealDto;
import com.itheima.reggie.exception.CustomerException;
import com.itheima.reggie.mappers.CategoryMapper;
import com.itheima.reggie.mappers.DishMapper;
import com.itheima.reggie.mappers.SetmealDishMapper;
import com.itheima.reggie.mappers.SetmealMapper;
import com.itheima.reggie.service.SetmealService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SetmealServiceImpl implements SetmealService {
    @Autowired(required = false)
    private SetmealMapper setmealMapper;

    @Autowired(required = false)
    private SetmealDishMapper setmealDishMapper;

    @Autowired(required = false)
    private CategoryMapper categoryMapper;

    @Autowired(required = false)
    private DishMapper dishMapper;

    @Override
    @CacheEvict(value = "setmeals",allEntries = true)
    public void save(SetmealDto setmealDto) {
        setmealDto.setCreateTime(LocalDateTime.now());
        setmealDto.setUpdateTime(LocalDateTime.now());
        setmealDto.setStatus(1);

        setmealMapper.save(setmealDto);

        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();

        setmealDishes = setmealDishes.stream().map(setmealDish -> {
            setmealDish.setSetmealId(setmealDto.getId());
            setmealDish.setCreateTime(LocalDateTime.now());
            setmealDish.setUpdateTime(LocalDateTime.now());
            setmealDish.setCreateUser(setmealDto.getCreateUser());
            setmealDish.setUpdateUser(setmealDto.getUpdateUser());
            setmealDish.setSort(0);
            return setmealDish;
        }).collect(Collectors.toList());

        setmealDishMapper.save(setmealDishes);

    }

    @Override
    public R<Page<SetmealDto>> findByPage(Integer page, Integer pageSize, String name) {

        PageHelper.startPage(page,pageSize);

        List<Setmeal> setmeals = setmealMapper.findByName(name);

        PageInfo<Setmeal> info = new PageInfo<>(setmeals);

        List<SetmealDto> setmealDtoList = setmeals.stream().map(setmeal -> {
            SetmealDto setmealDto = new SetmealDto();
            BeanUtils.copyProperties(setmeal, setmealDto);

            Category category = categoryMapper.findById(setmeal.getCategoryId());
            setmealDto.setCategoryName(category.getName());

            return setmealDto;
        }).collect(Collectors.toList());

        Page<SetmealDto> pageResult = new Page<>(setmealDtoList,info.getTotal(),page,pageSize);
        return R.success(pageResult);
    }

    @Override
    @CacheEvict(value = "setmeals",allEntries = true) // 缓存对数组比较难操作，所以全部删除
    public void delete(Long[] ids) {

        //1.根据id查询套餐，如果套餐在售，直接抛出业务异常
        Integer count = setmealMapper.findCountByStatus(ids);
        if (count > 0) {
            throw new CustomerException("不允许删除在售的套餐");
        }

        //2.删除套餐
        setmealMapper.delete(ids);

        //3.删除套餐关联的菜品
        setmealDishMapper.delete(ids);
    }

    @Override
    public R<SetmealDto> findBySetmealId(Long setmealId) {

        //通过id查找套餐
        Setmeal setmeal = setmealMapper.findById(setmealId);

        //把setmeal copy到setmealDto
        SetmealDto setmealDto = new SetmealDto();
        BeanUtils.copyProperties(setmeal,setmealDto);

        //通过id查找套餐对应菜品
        List<SetmealDish> setmealDishes = setmealDishMapper.findBySetmealId(setmealId);

        //用stream流设置setmealDto的List<SetmealDish>参数
        setmealDto.setSetmealDishes(setmealDishes);

        return R.success(setmealDto);
    }

    /**
     * 保存新的套餐不会影响其他的套餐属性，所以可以删除单个缓存数据，
     * 如果是更新数据，就需要删除所有的缓存数据
     * @param setmealDto
     */
    @Override
    // @CacheEvict(value = "setmeals",allEntries = true)
    @CacheEvict(value = "setmeals",key = "#setmealDto.categoryId+'_'+#setmealDto.status")
    public void update(SetmealDto setmealDto) {
        //1.补全信息，更新套餐信息
        setmealDto.setUpdateTime(LocalDateTime.now());
        setmealMapper.update(setmealDto);

        //2.通过套餐的id删除套餐对应菜品信息
        setmealDishMapper.delete(new Long[]{setmealDto.getId()});

        //3.得到套餐对应菜品，批量操作补全信息
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes = setmealDishes.stream().map(setmealDish -> {
            setmealDish.setSetmealId(setmealDto.getId());
            setmealDish.setSort(0);
            setmealDish.setCreateUser(setmealDto.getUpdateUser());
            setmealDish.setUpdateUser(setmealDto.getUpdateUser());
            setmealDish.setCreateTime(LocalDateTime.now());
            setmealDish.setUpdateTime(LocalDateTime.now());
            return setmealDish;
        }).collect(Collectors.toList());

        //4.添加套餐对应菜品
        setmealDishMapper.save(setmealDishes);

    }

    @Override
    public void updateStatus(List<Long> ids, int status) {
        setmealMapper.updateStatus(ids,status);
    }

    @Override
    @Cacheable(value = "setmeals",key = "#categoryId+'_'+#status",unless = "#result=null")
    public List<Setmeal> findByCategoryId(Long categoryId, int status) {
        List<Setmeal> setmeals = setmealMapper.findByCategoryId(categoryId, status);

        return setmeals;
    }

    @Override
    public R<List<Dish>> getBySetmealId(Long id) {
        List<SetmealDish> setmealDishes = setmealDishMapper.findBySetmealId(id);

        List<Dish> dishes = new ArrayList<>();
        for (SetmealDish setmealDish : setmealDishes) {
            Dish dish = dishMapper.findById(setmealDish.getDishId());
            dishes.add(dish);
        }

        return R.success(dishes);
    }


}
